home *** CD-ROM | disk | FTP | other *** search
/ Greenhouse Effect Detection Expriment / NASA Greenhouse Effect Detection Expriment 1992 - Disc 2.iso / software / dos / cdf22pc / src / lib / cdfrw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-13  |  31.1 KB  |  1,039 lines

  1. /******************************************************************************
  2. *
  3. *  NSSDC/CDF                        Read/write CDFs.
  4. *
  5. *  Version 1.0, 14-Feb-92, ST Systems (STX)
  6. *
  7. *  Modification history:
  8. *
  9. *   V1.0  14-Feb-92, J Love    Original version.  These functions were taken
  10. *                out of `cdflib.c'.
  11. *
  12. ******************************************************************************/
  13.  
  14. #include "cdflib.h"
  15.  
  16. #if defined(vms)         /* THIS FUNCTIONS IS ONLY USED ON VMS SYSTEMS */
  17. /******************************************************************************
  18. *  Read a CDF Version 1.1 header (.CDF & .CDH).
  19. *
  20. *  Those lines marked N/A don't necessary apply to Version 1 CDFs but are
  21. *  included to be consistent with the processing of V2.0+ CDFs.
  22. ******************************************************************************/
  23.  
  24. CDFstatus read_V1_header (CDF)
  25. struct cdfSTRUCT *CDF;
  26. {
  27. char var_datatype[V1_DATATYPE_STRING_LEN+1];
  28. char attr_datatype[V1_DATATYPE_STRING_LEN+1];
  29. struct attrSTRUCT *Attr;
  30. struct entrySTRUCT *Entry;
  31. struct varSTRUCT *Var;
  32. long attrid;
  33. long entryid;
  34. long reclength;
  35. long NattrRecs;
  36. long i;
  37. long offset;
  38. long data_bytesize;
  39. long tmp;
  40. long attrRecN;
  41. long Nbytes;
  42. long possNrecs;
  43. long varNum;
  44. int stat;
  45. File *fp;
  46. CDFstatus Pstatus = CDF_OK;            /* pending status */
  47. CDFstatus Tstatus;                /* temporary status */
  48. CDFstatus status;
  49. char tmp_filename[CDF_PATHNAME_LEN+4+1];    /* +4+1 for .CDF/.CDH and
  50.                            NUL-terminator */
  51.  
  52. /* Fill in CDF version 2 data structures with version 1 data */
  53.  
  54. CDF->CDRoffset = 0;                        /* N/A */
  55. CDF->CDR.RecordSize = 0;                    /* N/A */
  56. CDF->CDR.RecordType = 0;                    /* N/A */
  57. CDF->CDR.GDRoffset = 0;                        /* N/A */
  58.  
  59. CDF->CDR.Version = 1;
  60. CDF->CDR.Release = 1;
  61.  
  62. CDF->CDR.Encoding = VAX_ENCODING;
  63.  
  64. CDF->CDR.Flags = 0;
  65. clrbit(CDF->CDR.Flags,CDF_MAJORITY_BIT);
  66. clrbit(CDF->CDR.Flags,CDF_FORMAT_BIT);
  67.  
  68. CDF->CDR.rfuA = 0;                        /* N/A */
  69. CDF->CDR.rfuB = 0;                        /* N/A */
  70.  
  71. CDF->CDR.Increment = 0;            /* always 0 for Version 1 CDFs */
  72.  
  73. CDF->CDR.rfuD = -1;                        /* N/A */
  74. CDF->CDR.rfuE = -1;                        /* N/A */
  75.  
  76. strcpy (CDF->CDR.copyright,
  77.     "\nNo copyright text for a Version 1.1 CDF\n");
  78.  
  79. /* Skip over Header Record */
  80. /* Skip over FDR's */
  81.  
  82. Seek (CDF->fp, V1_GDR_OFFSET, SEEK_SET);
  83.  
  84. /* Read in GDR record */
  85.  
  86. CDF->GDRoffset = 0;                        /* N/A */
  87. CDF->GDR.RecordSize = 0;                    /* N/A */
  88. CDF->GDR.RecordType = 0;                    /* N/A */
  89. CDF->GDR.VDRhead = 0;                        /* N/A */
  90. CDF->GDR.garbage1 = 0;                        /* N/A */
  91. CDF->GDR.ADRhead = 0;                        /* N/A */
  92. CDF->GDR.eof = 0;                        /* N/A */
  93.  
  94. CDF->GDR.rfuA = 0;                        /* N/A */
  95. CDF->GDR.rfuB = 0;                        /* N/A */
  96. CDF->GDR.rfuC = 0;                        /* N/A */
  97. CDF->GDR.rfuD = -1;                        /* N/A */
  98. CDF->GDR.rfuE = -1;                        /* N/A */
  99.  
  100. CDF->GDR.DimSizes = (long *) malloc (V1_MAX_DIMS*sizeof(Int32));
  101. if (CDF->GDR.DimSizes == NULL) return BAD_MALLOC;
  102.  
  103. for (i=0;i<V1_MAX_DIMS;i++)
  104.    getint32H(CDF->fp,CDF->GDR.DimSizes[i]);
  105.  
  106. getint32H(CDF->fp,CDF->GDR.NumDims);
  107. getint32H(CDF->fp,CDF->GDR.NumVar);
  108.  
  109. getint32H(CDF->fp,tmp);
  110. CDF->GDR.MaxRec = tmp - 1;
  111.  
  112. /* Seek to first VDR */
  113.  
  114. if (CDF->GDR.NumVar > 0)
  115.   Seek (CDF->fp, V1_FIRST_VDR_OFFSET, SEEK_SET);
  116.  
  117. for(varNum=0;varNum<CDF->GDR.NumVar;varNum++){
  118.    Var = (struct varSTRUCT *) malloc (sizeof(struct varSTRUCT));
  119.    if (Var == NULL) return BAD_MALLOC;
  120.  
  121.    if (varNum == 0) {
  122.      CDF->varHead = Var;
  123.      CDF->varTail = Var;
  124.    }
  125.    else {
  126.      CDF->varTail->varNext = Var;
  127.      CDF->varTail = Var;
  128.    }
  129.  
  130.    Var->varNext = (struct varSTRUCT *) NULL;
  131.  
  132.    Var->VDRoffset = 0;                        /* N/A */
  133.    Var->vixHead = 0;                        /* N/A */
  134.    Var->vixTail = 0;                        /* N/A */
  135.  
  136.    Var->VDR.RecordSize = 0;                    /* N/A */
  137.    Var->VDR.RecordType = 0;                    /* N/A */
  138.    Var->VDR.VDRnext = 0;                    /* N/A */
  139.  
  140.    getbytes (V1_DATATYPE_STRING_LEN, var_datatype, CDF->fp);
  141.    var_datatype[V1_DATATYPE_STRING_LEN] = '\0';
  142.    if(strcmp("INT*4   ",var_datatype) == 0)
  143.       Var->VDR.DataType = CDF_INT4;
  144.    else if(strcmp("REAL*8  ",var_datatype) == 0)
  145.       Var->VDR.DataType = CDF_REAL8;
  146.    else if(strcmp("REAL*4  ",var_datatype) == 0)
  147.       Var->VDR.DataType = CDF_REAL4;
  148.    else if(strcmp("STRING  ",var_datatype) == 0)
  149.       Var->VDR.DataType = CDF_CHAR;
  150.    else if(strcmp("INT*2   ",var_datatype) == 0)
  151.       Var->VDR.DataType = CDF_INT2;
  152.    else if(strcmp("BYTE    ",var_datatype) == 0)
  153.       Var->VDR.DataType = CDF_BYTE;
  154.    else
  155.       return CORRUPTED_V1_CDF;                /* CLEAN UP! */
  156.  
  157.    for (i=0;i<V1_MAX_DIMS;i++)
  158.       getint32H(CDF->fp,tmp);            /* skip dimension map */
  159.  
  160.    Var->VDR.VXRhead = 0;                    /* N/A */
  161.    Var->VDR.VXRtail = 0;                    /* N/A */
  162.  
  163.    Var->VDR.Flags = 0;
  164.    getint32H(CDF->fp,tmp);
  165.  
  166.    if (tmp)
  167.      setbit(Var->VDR.Flags,VAR_RECVARY_BIT);
  168.     else
  169.      clrbit(Var->VDR.Flags,VAR_RECVARY_BIT);
  170.  
  171.    clrbit(Var->VDR.Flags,VAR_FILLVALUE_BIT);            /* N/A */
  172.  
  173.    Var->VDR.rfuA = 0;                        /* N/A */
  174.    Var->VDR.rfuB = 0;                        /* N/A */
  175.    Var->VDR.rfuC = -1;                        /* N/A */
  176.    Var->VDR.REFvarNum = -1;                    /* N/A */
  177.    Var->VDR.REFfilename[0] = NUL;                /* N/A */
  178.  
  179.    Var->VDR.DimVarys = (long *) malloc (V1_MAX_DIMS*sizeof(Int32));
  180.    if (Var->VDR.DimVarys == NULL) return BAD_MALLOC;
  181.  
  182.    for (i = 0; i < V1_MAX_DIMS; i++) {
  183.       getint32H(CDF->fp,tmp);
  184.       if (tmp)
  185.         Var->VDR.DimVarys[i] = VARY;
  186.        else
  187.         Var->VDR.DimVarys[i] = NOVARY;
  188.    }
  189.  
  190.    getint32H(CDF->fp,tmp);            /* skip variable rank */
  191.  
  192.    for (i=0;i<V1_MAX_DIMS;i++)
  193.       getint32H(CDF->fp,tmp);            /* skip products */
  194.  
  195.    getint32H(CDF->fp,tmp);            /* skip total size */
  196.    getint32H(CDF->fp,tmp);            /* skip trans number*/
  197.  
  198.    getint32H(CDF->fp,Var->VDR.NumElem);
  199.    if (Var->VDR.DataType != CDF_CHAR) Var->VDR.NumElem = 1;
  200.  
  201.    Var->VDR.rfuD = -1;                        /* N/A */
  202.    Var->VDR.NextendRecs = 0;                    /* N/A */
  203.    Var->VDR.FillValue = NULL;                    /* N/A */
  204.  
  205.    getbytes (V1_VAR_NAME_LEN, Var->VDR.Name, CDF->fp);
  206.    Var->VDR.Name[V1_VAR_NAME_LEN] = NUL;
  207.  
  208.    /***************************************************************************
  209.    * Check if data type should be changed to CDF_EPOCH.
  210.    ***************************************************************************/
  211.  
  212. #if NSSDC_STANDARD
  213.    if (strcmpITB(Var->VDR.Name,"EPOCH") == 0 && Var->VDR.DataType == CDF_REAL8)
  214.      Var->VDR.DataType = CDF_EPOCH;
  215. #endif
  216.  
  217.    Var->status = VAR_CLOSED;            /* V1 CDFs are always MULTI */
  218.  
  219.    if (CDF->GDR.NumDims > 0) {
  220.      Nbytes = CDF->GDR.NumDims * sizeof(long);
  221.      Var->products = (long *) malloc (Nbytes);
  222.      if (Var->products == NULL) return BAD_MALLOC;
  223.      Var->hypProducts = (long *) malloc (Nbytes);
  224.      if (Var->hypProducts == NULL) return BAD_MALLOC;
  225.      Var->hypIndices = (long *) malloc (Nbytes);
  226.      if (Var->hypIndices == NULL) return BAD_MALLOC;
  227.      Var->hypTops = (long *) malloc (Nbytes);
  228.      if (Var->hypTops == NULL) return BAD_MALLOC;
  229.    }
  230.    else {
  231.      Var->products = NULL;
  232.      Var->hypProducts = NULL;
  233.      Var->hypIndices = NULL;
  234.      Var->hypTops = NULL;
  235.    }
  236.  
  237.    Var->seqValueOffset = 0;
  238.  
  239.    calcVarParms (CDF, Var);
  240.  
  241.    Var->VDR.Num = varNum;
  242.  
  243. /******************************************************************************
  244. * The number of records per variable wasn't kept in Version 1 - this could
  245. * be a problem if not every variable (with TRUE record variance) has the
  246. * same number of records
  247. ******************************************************************************/
  248.  
  249. #if GUESS_V1_VECTOR_SIZES
  250.    if (bitset(Var->VDR.Flags,VAR_RECVARY_BIT))
  251.       Var->VDR.MaxRec = CDF->GDR.MaxRec;
  252.     else
  253.       Var->VDR.MaxRec = (CDF->GDR.MaxRec == -1 ? -1 : 0);
  254. #else
  255.    /***************************************************************************
  256.    * Not guessing.  Note that this algorithm isn't perfect (but I don't think
  257.    * it can be improved either).  If there is room for additional records in
  258.    * the last block, they will be counted even if they were never actually
  259.    * PUT.  They won't be counted, however, if they are past the number of
  260.    * records for the entire CDF (the only thing stored by CDF V1.1).
  261.    *
  262.    * Note also that the 'status' returned from opening the variable file isn't
  263.    * returned to the caller if something went wrong.  This is because some
  264.    * CDF V1.1-based systems deleted empty vector files if Puts would never be
  265.    * done to the associated variable.  This way an error won't be reported to
  266.    * the user until the variable is accessed (which shouldn't happen).
  267.    ***************************************************************************/
  268.  
  269.    status = OpenVar (CDF, Var);
  270.    if (status < CDF_WARN)
  271.      Nbytes = 0;
  272.    else {
  273.      Seek (Var->fp, 0, SEEK_END);
  274.      Nbytes = Tell (Var->fp);       /* EOF offset = number of bytes in file */
  275.      Close (Var->fp);
  276.    }
  277.    Var->status = VAR_CLOSED;
  278.  
  279.    possNrecs = Nbytes / Var->NphyRecBytes;
  280.  
  281.    if (bitset(Var->VDR.Flags,VAR_RECVARY_BIT))
  282.      Var->VDR.MaxRec = Minimum (CDF->GDR.MaxRec, possNrecs - 1);
  283.     else
  284.      Var->VDR.MaxRec = Minimum (possNrecs - 1, 0);
  285. #endif
  286.  
  287.    CDF->var[varNum] = Var;
  288. }
  289.  
  290. /* Now read CDH attribute file */
  291.                 
  292. /* Open CDH file */
  293.  
  294. strcpy(tmp_filename,CDF->filename);
  295. strcat(tmp_filename,".cdh");
  296.  
  297. fp = OpenFile (tmp_filename,"rb");
  298. if (fp == NULL) return CDH_OPEN_ERROR;
  299.  
  300. getint32H(fp,NattrRecs);
  301. getint32H(fp,tmp);                    /* skip something */
  302. getint32H(fp,tmp);                    /* skip something */
  303. getint32H(fp,CDF->GDR.NumAttr);
  304.                 
  305. for (attrRecN = 0; attrRecN < NattrRecs-1; attrRecN++) {
  306.    getint32H(fp,reclength);
  307.    getint32H(fp,attrid);
  308.    getint32H(fp,entryid);
  309.    if(entryid == 0){
  310.       /* Attribute Descriptor Record */
  311.       Attr = (struct attrSTRUCT *) malloc (sizeof(struct attrSTRUCT));
  312.       if (Attr == NULL) return BAD_MALLOC;
  313.  
  314.       if (CDF->attrHead == NULL) {
  315.     CDF->attrHead = Attr;
  316.     CDF->attrTail = Attr;
  317.       }
  318.       else {
  319.     CDF->attrTail->attrNext = Attr;
  320.     CDF->attrTail = Attr;
  321.       }
  322.  
  323.       Attr->attrNext = (struct attrSTRUCT *) NULL;
  324.  
  325.       Attr->ADRoffset = 0;                    /* N/A */
  326.       Attr->ADR.RecordSize = 0;                    /* N/A */
  327.       Attr->ADR.RecordType = 0;                    /* N/A */
  328.       Attr->ADR.ADRnext = 0;                    /* N/A */
  329.       Attr->ADR.AEDRhead = 0;                    /* N/A */
  330.  
  331.       Attr->ADR.Num = attrid - 1;
  332.  
  333.       getint32H(fp,Attr->V1numBytes);
  334.  
  335.       getint32H(fp,tmp);
  336.       Attr->ADR.MaxEntry = tmp - 1;
  337.  
  338.       Attr->ADR.NumEntries = 0;    /* this will be incremented as
  339.                        AEDRs are read */
  340.  
  341.       Attr->ADR.rfuA = 0;                    /* N/A */
  342.       Attr->ADR.rfuB = 0;                    /* N/A */
  343.       Attr->ADR.rfuC = 0;                    /* N/A */
  344.       Attr->ADR.rfuD = -1;                    /* N/A */
  345.       Attr->ADR.rfuE = -1;                    /* N/A */
  346.  
  347.       if (Attr->ADR.MaxEntry == 0)
  348.      Attr->ADR.Scope = GLOBAL_SCOPE_ASSUMED;
  349.        else
  350.      Attr->ADR.Scope = VARIABLE_SCOPE_ASSUMED;
  351.  
  352.       getbytes (V1_ATTR_NAME_LEN, Attr->ADR.Name, fp);
  353.       Attr->ADR.Name[V1_ATTR_NAME_LEN] = NUL;
  354.  
  355.       getbytes (V1_DATATYPE_STRING_LEN, attr_datatype, fp);
  356.       attr_datatype[V1_DATATYPE_STRING_LEN] = '\0';
  357.  
  358.       if (strcmp("INT*4   ",attr_datatype) == 0)
  359.          Attr->V1dataType = CDF_INT4;
  360.       else if(strcmp("REAL*8  ",attr_datatype) == 0)
  361.          Attr->V1dataType = CDF_REAL8;
  362.       else if(strcmp("REAL*4  ",attr_datatype) == 0)
  363.          Attr->V1dataType = CDF_REAL4;
  364.       else if(strcmp("STRING  ",attr_datatype) == 0)
  365.          Attr->V1dataType = CDF_CHAR;
  366.       else if(strcmp("INT*2   ",attr_datatype) == 0)
  367.          Attr->V1dataType = CDF_INT2;
  368.       else if(strcmp("BYTE    ",attr_datatype) == 0)
  369.          Attr->V1dataType = CDF_BYTE;
  370.       else
  371.      return CORRUPTED_V1_CDF;
  372.  
  373.       Attr->entryHead = NULL;
  374.       Attr->entryTail = NULL;
  375.    }
  376.    else {
  377.    /* Must be an attribute record */
  378.  
  379.    /* First find corresponding attribute descriptor record */
  380.  
  381.    Attr = CDF->attrHead;
  382.    while (Attr != NULL) {
  383.       if (Attr->ADR.Num == attrid - 1) break;
  384.       Attr = Attr->attrNext;
  385.    }
  386.    if (Attr == NULL) return CORRUPTED_V1_CDF;
  387.  
  388.    Entry = (struct entrySTRUCT *) malloc (sizeof(struct entrySTRUCT));
  389.    if (Entry == NULL) return BAD_MALLOC;
  390.  
  391.    if (Attr->entryHead == NULL) {
  392.      Attr->entryHead = Entry;
  393.      Attr->entryTail = Entry;
  394.    }
  395.    else {
  396.      Attr->entryTail->entryNext = Entry;
  397.      Attr->entryTail = Entry;
  398.    }
  399.  
  400.    Entry->entryNext = (struct entrySTRUCT *) NULL;
  401.  
  402.    Entry->AEDRoffset = 0;                    /* N/A */
  403.    Entry->AEDR.RecordSize = 0;                    /* N/A */
  404.    Entry->AEDR.RecordType = 0;                    /* N/A */
  405.    Entry->AEDR.AEDRnext = 0;                    /* N/A */
  406.  
  407.    /* fill in attribute value record */
  408.                 
  409.    Entry->AEDR.AttrNum = attrid - 1;
  410.    Entry->AEDR.DataType = Attr->V1dataType;
  411.    Entry->AEDR.Num = entryid - 1;
  412.  
  413.    Attr->ADR.NumEntries++;   /* tally an attribute entry */
  414.  
  415.    if(Entry->AEDR.DataType == CDF_CHAR)
  416.       Entry->AEDR.NumElem = Attr->V1numBytes;
  417.     else
  418.       Entry->AEDR.NumElem = 1;
  419.  
  420.    Entry->AEDR.rfuA = 0;                    /* N/A */
  421.    Entry->AEDR.rfuB = 0;                    /* N/A */
  422.    Entry->AEDR.rfuC = 0;                    /* N/A */
  423.    Entry->AEDR.rfuD = -1;                    /* N/A */
  424.    Entry->AEDR.rfuE = -1;                    /* N/A */
  425.  
  426.    Entry->AEDR.Value = (void *) malloc (Attr->V1numBytes);
  427.    if (Entry->AEDR.Value == NULL) return BAD_MALLOC;
  428.  
  429.    getbytes (Attr->V1numBytes, Entry->AEDR.Value, fp);
  430.  
  431.    /***************************************************************************
  432.    * Check if entry data type should be changed to CDF_EPOCH.  Note that the
  433.    * data type of the "EPOCH" variable will have already been changed to
  434.    * CDF_EPOCH.
  435.    ***************************************************************************/
  436.  
  437. #if NSSDC_STANDARD
  438.    if ((strcmpITB(Attr->ADR.Name,"VALIDMIN") == 0 ||
  439.         strcmpITB(Attr->ADR.Name,"VALIDMAX") == 0 ||
  440.         strcmpITB(Attr->ADR.Name,"SCALEMIN") == 0 ||
  441.         strcmpITB(Attr->ADR.Name,"SCALEMAX") == 0) &&
  442.        Entry->AEDR.DataType == CDF_REAL8) {
  443.      Var = CDF->var[Entry->AEDR.Num];
  444.      if (Var != NULL)
  445.        if (Var->VDR.DataType == CDF_EPOCH) Entry->AEDR.DataType = CDF_EPOCH;
  446.    }
  447. #endif
  448.  
  449.    }
  450. }
  451.  
  452. /* close .CDH (.CDF stays open just like V2 CDFs) */
  453.  
  454. stat = Close (fp);
  455. if (stat == EOF) return CDH_CLOSE_ERROR;
  456.  
  457. return Pstatus;
  458. }
  459. #endif
  460.  
  461. /******************************************************************************
  462. *  Read a CDF Version 2.0/2.1 header (.CDF).
  463. ******************************************************************************/
  464.  
  465. CDFstatus read_V2_header (CDF)
  466. struct cdfSTRUCT *CDF;
  467. {
  468. struct attrSTRUCT  *Attr;
  469. struct entrySTRUCT *Entry;
  470. struct varSTRUCT   *Var;
  471. struct vixSTRUCT   *Vix;
  472. long           data_bytesize,Nbytes;
  473. long           VXRi,VDRi,ADRi,AEDRi;
  474. CDFstatus       Pstatus = CDF_OK;
  475. long           dimN;
  476. long           i;
  477.  
  478. /*** Fill in CDR ***/
  479.  
  480. CDF->CDRoffset = V2_CDR_OFFSET;
  481. Seek (CDF->fp, CDF->CDRoffset, SEEK_SET);
  482.  
  483. getint32(CDF->fp,CDF->CDR.RecordSize);
  484. getint32(CDF->fp,CDF->CDR.RecordType);
  485. if(CDF->CDR.RecordType != CDR_) return CORRUPTED_V2_CDF;    /* CLEAN UP! */
  486.  
  487. getint32(CDF->fp,CDF->CDR.GDRoffset);
  488. getint32(CDF->fp,CDF->CDR.Version);
  489. getint32(CDF->fp,CDF->CDR.Release);
  490.  
  491. getint32(CDF->fp,CDF->CDR.Encoding);
  492.  
  493. if (CDF->CDR.Encoding != NETWORK_ENCODING &&
  494.     CDF->CDR.Encoding != _CDFhostEncoding) {
  495.   switch (CDF->CDR.Encoding) {
  496.     case VAX_ENCODING: return VAX_ENCODING_UNSUPPORTED;
  497.     case SUN_ENCODING: return SUN_ENCODING_UNSUPPORTED;
  498.     case MIPSEB_ENCODING: return MIPSEB_ENCODING_UNSUPPORTED;
  499.     case MIPSEL_ENCODING: return MIPSEL_ENCODING_UNSUPPORTED;
  500.     case IBMPC_ENCODING: return IBMPC_ENCODING_UNSUPPORTED;
  501.     case IBMRS_ENCODING: return IBMRS_ENCODING_UNSUPPORTED;
  502.     case HP_ENCODING: return HP_ENCODING_UNSUPPORTED;
  503.     default: return CORRUPTED_V2_CDF;
  504.   }
  505. }
  506.  
  507. getint32(CDF->fp,CDF->CDR.Flags);
  508. getint32(CDF->fp,CDF->CDR.rfuA);
  509. getint32(CDF->fp,CDF->CDR.rfuB);
  510. getint32(CDF->fp,CDF->CDR.Increment);
  511. getint32(CDF->fp,CDF->CDR.rfuD);
  512. getint32(CDF->fp,CDF->CDR.rfuE);
  513.  
  514. getbytes(CDF_COPYRIGHT_LEN,CDF->CDR.copyright,CDF->fp);
  515.             
  516. /* Fill in GDR data structure */
  517.  
  518. CDF->GDRoffset = CDF->CDR.GDRoffset;
  519. Seek (CDF->fp, CDF->GDRoffset, SEEK_SET);
  520.  
  521. getint32(CDF->fp,CDF->GDR.RecordSize);
  522. getint32(CDF->fp,CDF->GDR.RecordType);
  523. if(CDF->GDR.RecordType != GDR_) return CORRUPTED_V2_CDF;    /* CLEAN UP! */
  524.  
  525. getint32(CDF->fp,CDF->GDR.VDRhead);
  526. getint32(CDF->fp,CDF->GDR.garbage1);
  527. getint32(CDF->fp,CDF->GDR.ADRhead);
  528. getint32(CDF->fp,CDF->GDR.eof);        /* random value if V2.0 CDF */
  529. getint32(CDF->fp,CDF->GDR.NumVar);
  530. getint32(CDF->fp,CDF->GDR.NumAttr);
  531. getint32(CDF->fp,CDF->GDR.MaxRec);
  532. getint32(CDF->fp,CDF->GDR.NumDims);
  533. getint32(CDF->fp,CDF->GDR.rfuA);
  534. getint32(CDF->fp,CDF->GDR.rfuB);
  535. getint32(CDF->fp,CDF->GDR.rfuC);
  536. getint32(CDF->fp,CDF->GDR.rfuD);
  537. getint32(CDF->fp,CDF->GDR.rfuE);
  538.  
  539. if (CDF->GDR.NumDims > 0) {
  540.   CDF->GDR.DimSizes = (Int32 *) malloc (CDF->GDR.NumDims * sizeof(Int32));
  541.   if (CDF->GDR.DimSizes == NULL) return BAD_MALLOC;
  542. }
  543. else
  544.   CDF->GDR.DimSizes = NULL;
  545.  
  546. for (dimN = 0; dimN < CDF->GDR.NumDims; dimN++)
  547.    getint32(CDF->fp,CDF->GDR.DimSizes[dimN]);
  548.  
  549. /* Read in VDRs - EXPLAIN PROBLEM WITH V2.0 OFFSETS */
  550.  
  551. for (VDRi = 0; VDRi < CDF->GDR.NumVar; VDRi++) {
  552.    Var = (struct varSTRUCT *) malloc (sizeof(struct varSTRUCT));
  553.    if (Var == NULL) return BAD_MALLOC;
  554.  
  555.    if (VDRi == 0) {
  556.       Var->VDRoffset = CDF->GDR.VDRhead;
  557.       CDF->varHead = Var;
  558.       CDF->varTail = Var;
  559.    }
  560.    else {
  561.       Var->VDRoffset = CDF->varTail->VDR.VDRnext;
  562.       CDF->varTail->varNext = Var;
  563.       CDF->varTail = Var;
  564.    }
  565.  
  566.    Var->varNext = (struct varSTRUCT *) NULL;
  567.  
  568.    Seek (CDF->fp, Var->VDRoffset, SEEK_SET);
  569.  
  570.    if (bitclr(CDF->CDR.Flags,CDF_FORMAT_BIT))
  571.      Var->status = VAR_CLOSED;
  572.    else
  573.      Var->status = NO_VAR_FILE;
  574.  
  575.    getint32(CDF->fp,Var->VDR.RecordSize);
  576.    getint32(CDF->fp,Var->VDR.RecordType);
  577.    if(Var->VDR.RecordType != VDR_) return CORRUPTED_V2_CDF;    /* CLEAN UP! */
  578.  
  579.    getint32(CDF->fp,Var->VDR.VDRnext);
  580.    getint32(CDF->fp,Var->VDR.DataType);
  581.    getint32(CDF->fp,Var->VDR.MaxRec);
  582.    getint32(CDF->fp,Var->VDR.VXRhead);
  583.    getint32(CDF->fp,Var->VDR.VXRtail);
  584.    getint32(CDF->fp,Var->VDR.Flags);
  585.    getint32(CDF->fp,Var->VDR.rfuA);
  586.    getint32(CDF->fp,Var->VDR.rfuB);
  587.    getint32(CDF->fp,Var->VDR.rfuC);
  588.    getint32(CDF->fp,Var->VDR.REFvarNum);
  589.  
  590.    getbytes(CDF_VAR_FILE_NAME_LEN,Var->VDR.REFfilename,CDF->fp);
  591.    Var->VDR.REFfilename[CDF_VAR_FILE_NAME_LEN] = NUL;
  592.  
  593.    getint32(CDF->fp,Var->VDR.NumElem);
  594.    getint32(CDF->fp,Var->VDR.Num);
  595.    getint32(CDF->fp,Var->VDR.rfuD);
  596.    getint32(CDF->fp,Var->VDR.NextendRecs);
  597.  
  598.    getbytes(CDF_VAR_NAME_LEN,Var->VDR.Name,CDF->fp);
  599.    Var->VDR.Name[CDF_VAR_NAME_LEN] = NUL;
  600.  
  601.    if (CDF->GDR.NumDims > 0) {
  602.      Var->VDR.DimVarys = (Int32 *) malloc (CDF->GDR.NumDims * sizeof(Int32));
  603.      if (Var->VDR.DimVarys == NULL) return BAD_MALLOC;        /* CLEAN UP! */
  604.      for (dimN = 0; dimN < CDF->GDR.NumDims; dimN++)
  605.         getint32(CDF->fp,Var->VDR.DimVarys[dimN]);
  606.    }
  607.    else
  608.      Var->VDR.DimVarys = NULL;
  609.  
  610.    if (bitset(Var->VDR.Flags,VAR_FILLVALUE_BIT)) {
  611.      /*** can't use NvalueBytes - not calculated yet ***/
  612.      Var->VDR.FillValue = (void *) malloc (Var->VDR.NumElem *
  613.                        _CDFelemSizes[Var->VDR.DataType]);
  614.      if (Var->VDR.FillValue == NULL) return BAD_MALLOC;
  615.      getbytes (Var->VDR.NumElem * _CDFelemSizes[Var->VDR.DataType],
  616.            Var->VDR.FillValue, CDF->fp);
  617.      DecodeBuffer (CDF->CDR.Encoding, Var->VDR.DataType,
  618.            Var->VDR.NumElem, Var->VDR.FillValue);
  619.    }
  620.    else
  621.      Var->VDR.FillValue = NULL;
  622.  
  623.    /***************************************************************************
  624.    * Check if data type should be changed to CDF_EPOCH.
  625.    ***************************************************************************/
  626.  
  627. #if NSSDC_STANDARD
  628.    if (CDF->CDR.Release == 0 ||
  629.        (CDF->CDR.Release == 1 && CDF->CDR.Increment < 1))
  630.      if (strcmpITB(Var->VDR.Name,"EPOCH") == 0 &&
  631.      (Var->VDR.DataType == CDF_REAL8 || Var->VDR.DataType == CDF_DOUBLE))
  632.        Var->VDR.DataType = CDF_EPOCH;
  633. #endif
  634.  
  635.    if (CDF->GDR.NumDims > 0) {
  636.      Nbytes = CDF->GDR.NumDims * sizeof(Int32);
  637.      Var->products = (long *) malloc (Nbytes);
  638.      if (Var->products == NULL) return BAD_MALLOC;
  639.      Var->hypProducts = (long *) malloc (Nbytes);
  640.      if (Var->hypProducts == NULL) return BAD_MALLOC;
  641.      Var->hypIndices = (long *) malloc (Nbytes);
  642.      if (Var->hypIndices == NULL) return BAD_MALLOC;
  643.      Var->hypTops = (long *) malloc (Nbytes);
  644.      if (Var->hypTops == NULL) return BAD_MALLOC;
  645.    }
  646.    else {
  647.      Var->products = NULL;
  648.      Var->hypProducts = NULL;
  649.      Var->hypIndices = NULL;
  650.      Var->hypTops = NULL;
  651.    }
  652.  
  653.    Var->seqValueOffset = 0;
  654.  
  655.    calcVarParms (CDF, Var);
  656.  
  657.    /*** if this is a SINGLE file CDF, set the Var's fp to that of the CDF ***/
  658.  
  659.    if (bitset(CDF->CDR.Flags,CDF_FORMAT_BIT))
  660.      Var->fp = CDF->fp;
  661.    else
  662.      Var->fp = NULL;
  663.  
  664.    CDF->var[Var->VDR.Num] = Var;
  665.  
  666.    /*** read linked list of VXRs ***/
  667.  
  668.    Var->vixHead = (struct vixSTRUCT *) NULL;
  669.    Var->vixTail = (struct vixSTRUCT *) NULL;
  670.  
  671.    if (bitset(CDF->CDR.Flags,CDF_FORMAT_BIT))
  672.       if (Var->VDR.VXRhead != 0)
  673.     for (VXRi = 0; /*continue until 'break'*/; VXRi++) {
  674.        Vix = (struct vixSTRUCT *) malloc (sizeof(struct vixSTRUCT));
  675.        if (Vix == NULL) return BAD_MALLOC;
  676.  
  677.        if (VXRi == 0) {
  678.          Vix->VXRoffset = Var->VDR.VXRhead;
  679.          Var->vixHead = Vix;
  680.          Var->vixTail = Vix;
  681.        }
  682.        else {
  683.          Vix->VXRoffset = Var->vixTail->VXR.VXRnext;
  684.          Var->vixTail->vixNext = Vix;
  685.          Var->vixTail = Vix;
  686.        }
  687.  
  688.        Vix->vixNext = (struct vixSTRUCT *) NULL;
  689.  
  690.        Seek (CDF->fp, Vix->VXRoffset, SEEK_SET);
  691.  
  692.        getint32 (CDF->fp, Vix->VXR.RecordSize);
  693.        getint32 (CDF->fp, Vix->VXR.RecordType);
  694.        if (Vix->VXR.RecordType != VXR_)
  695.          return CORRUPTED_V2_CDF;                /* CLEAN UP! */
  696.  
  697.        getint32 (CDF->fp, Vix->VXR.VXRnext);
  698.        getint32 (CDF->fp, Vix->VXR.Nentries);
  699.        getint32 (CDF->fp, Vix->VXR.NusedEntries);
  700.  
  701.        Nbytes = Vix->VXR.Nentries * sizeof(Int32);
  702.        Vix->VXR.FirstRec = (Int32 *) malloc (Nbytes);
  703.        if (Vix->VXR.FirstRec == NULL) return BAD_MALLOC;
  704.        Vix->VXR.LastRec = (Int32 *) malloc (Nbytes);
  705.        if (Vix->VXR.LastRec == NULL) return BAD_MALLOC;
  706.        Vix->VXR.VVRoffset = (Int32 *) malloc (Nbytes);
  707.        if (Vix->VXR.VVRoffset == NULL) return BAD_MALLOC;
  708.  
  709.        for (i = 0; i < Vix->VXR.Nentries; i++)
  710.           getint32 (CDF->fp, Vix->VXR.FirstRec[i]);
  711.        for (i = 0; i < Vix->VXR.Nentries; i++)
  712.           getint32 (CDF->fp, Vix->VXR.LastRec[i]);
  713.        for (i = 0; i < Vix->VXR.Nentries; i++)
  714.           getint32 (CDF->fp, Vix->VXR.VVRoffset[i]);
  715.  
  716.        if (Vix->VXR.VXRnext == 0) break;
  717.     }
  718. }
  719.  
  720. /* Read in Attribute Descriptors - EXPLAIN PROBLEM WITH V2.0 OFFSETS */
  721.  
  722. for (ADRi = 0; ADRi < CDF->GDR.NumAttr; ADRi++) {
  723.    Attr = (struct attrSTRUCT *) malloc (sizeof(struct attrSTRUCT));
  724.    if (Attr == NULL) return BAD_MALLOC;
  725.  
  726.    if (ADRi == 0) {
  727.      Attr->ADRoffset = CDF->GDR.ADRhead;
  728.      CDF->attrHead = Attr;
  729.      CDF->attrTail = Attr;
  730.    }
  731.    else {
  732.      Attr->ADRoffset = CDF->attrTail->ADR.ADRnext;
  733.      CDF->attrTail->attrNext = Attr;
  734.      CDF->attrTail = Attr;
  735.    }
  736.  
  737.    Attr->attrNext = (struct attrSTRUCT *) NULL;
  738.  
  739.    Seek (CDF->fp, Attr->ADRoffset, SEEK_SET);
  740.  
  741.    getint32(CDF->fp,Attr->ADR.RecordSize);
  742.    getint32(CDF->fp,Attr->ADR.RecordType);
  743.    if(Attr->ADR.RecordType != ADR_) return CORRUPTED_V2_CDF;    /* CLEAN UP! */
  744.  
  745.    getint32(CDF->fp,Attr->ADR.ADRnext);
  746.    getint32(CDF->fp,Attr->ADR.AEDRhead);
  747.    getint32(CDF->fp,Attr->ADR.Scope);
  748.    getint32(CDF->fp,Attr->ADR.Num);
  749.    getint32(CDF->fp,Attr->ADR.NumEntries);
  750.    getint32(CDF->fp,Attr->ADR.MaxEntry);
  751.    getint32(CDF->fp,Attr->ADR.rfuA);
  752.    getint32(CDF->fp,Attr->ADR.rfuB);
  753.    getint32(CDF->fp,Attr->ADR.rfuC);
  754.    getint32(CDF->fp,Attr->ADR.rfuD);
  755.    getint32(CDF->fp,Attr->ADR.rfuE);
  756.  
  757.    getbytes(CDF_ATTR_NAME_LEN,Attr->ADR.Name,CDF->fp);
  758.    Attr->ADR.Name[CDF_ATTR_NAME_LEN] = NUL;
  759.  
  760.    /*** read in AEDRs - EXPLAIN PROBLEM WITH V2.0 OFFSETS ***/
  761.  
  762.    Attr->entryHead = NULL;
  763.    Attr->entryTail = NULL;
  764.  
  765.    for (AEDRi = 0; AEDRi < Attr->ADR.NumEntries; AEDRi++) {
  766.       Entry = (struct entrySTRUCT *) malloc (sizeof(struct entrySTRUCT));
  767.       if (Entry == NULL) return BAD_MALLOC;
  768.  
  769.       if (AEDRi == 0) {
  770.     Entry->AEDRoffset = Attr->ADR.AEDRhead;
  771.     Attr->entryHead = Entry;
  772.     Attr->entryTail = Entry;
  773.       }
  774.       else {
  775.     Entry->AEDRoffset = Attr->entryTail->AEDR.AEDRnext;
  776.     Attr->entryTail->entryNext = Entry;
  777.     Attr->entryTail = Entry;
  778.       }
  779.  
  780.       Entry->entryNext = (struct entrySTRUCT *) NULL;
  781.  
  782.       Seek (CDF->fp, Entry->AEDRoffset, SEEK_SET);
  783.                 
  784.       getint32(CDF->fp,Entry->AEDR.RecordSize);
  785.       getint32(CDF->fp,Entry->AEDR.RecordType);
  786.       if (Entry->AEDR.RecordType != AEDR_)
  787.     return CORRUPTED_V2_CDF;                /* CLEAN UP!*/
  788.  
  789.       getint32(CDF->fp,Entry->AEDR.AEDRnext);
  790.       getint32(CDF->fp,Entry->AEDR.AttrNum);
  791.       getint32(CDF->fp,Entry->AEDR.DataType);
  792.       getint32(CDF->fp,Entry->AEDR.Num);
  793.       getint32(CDF->fp,Entry->AEDR.NumElem);
  794.       getint32(CDF->fp,Entry->AEDR.rfuA);
  795.       getint32(CDF->fp,Entry->AEDR.rfuB);
  796.       getint32(CDF->fp,Entry->AEDR.rfuC);
  797.       getint32(CDF->fp,Entry->AEDR.rfuD);
  798.       getint32(CDF->fp,Entry->AEDR.rfuE);
  799.  
  800.       data_bytesize = _CDFelemSizes[Entry->AEDR.DataType] *
  801.               Entry->AEDR.NumElem;
  802.       Entry->AEDR.Value = (void *) malloc (data_bytesize);
  803.       if (Entry->AEDR.Value == NULL) return BAD_MALLOC;
  804.  
  805.       getbytes(data_bytesize,Entry->AEDR.Value,CDF->fp);
  806.  
  807.       DecodeBuffer (CDF->CDR.Encoding, Entry->AEDR.DataType,
  808.             Entry->AEDR.NumElem, Entry->AEDR.Value);
  809.  
  810.       /************************************************************************
  811.       * Check if entry data type should be changed to CDF_EPOCH.  Note that
  812.       * that data type of the "EPOCH" variable will have already been changed
  813.       * to CDF_EPOCH.
  814.       ************************************************************************/
  815.  
  816. #if NSSDC_STANDARD
  817.       if (CDF->CDR.Release == 0 ||
  818.       (CDF->CDR.Release == 1 && CDF->CDR.Increment < 1))
  819.     if ((strcmpITB(Attr->ADR.Name,"VALIDMIN") == 0 ||
  820.          strcmpITB(Attr->ADR.Name,"VALIDMAX") == 0 ||
  821.          strcmpITB(Attr->ADR.Name,"SCALEMIN") == 0 ||
  822.          strcmpITB(Attr->ADR.Name,"SCALEMAX") == 0) &&
  823.         (Entry->AEDR.DataType == CDF_REAL8 ||
  824.          Entry->AEDR.DataType == CDF_DOUBLE)) {
  825.       Var = CDF->var[Entry->AEDR.Num];
  826.       if (Var != NULL)
  827.         if (Var->VDR.DataType == CDF_EPOCH)
  828.           Entry->AEDR.DataType = CDF_EPOCH;
  829.     }
  830. #endif
  831.    }
  832. }
  833.  
  834. if (CDF->CDR.Release == 0) calc_V20_eof (CDF);    /* necessary for V2.0
  835.                                CDFs only */
  836. return Pstatus;
  837. }
  838.  
  839. /******************************************************************************
  840. *  Write a CDF Version 2.0 header (.CDF).
  841. ******************************************************************************/
  842.  
  843. CDFstatus write_V2_header (CDF)
  844. struct cdfSTRUCT *CDF;
  845. {
  846. struct attrSTRUCT *Attr;
  847. struct entrySTRUCT *Entry;
  848. struct varSTRUCT *Var;
  849. struct vixSTRUCT *Vix;
  850. long Nbytes;
  851. CDFstatus Pstatus = CDF_OK;
  852. long i;
  853. long dimN;
  854.  
  855. /* Write out magic number(s) */
  856.  
  857. Seek (CDF->fp, V2_MAGIC_OFFSET, SEEK_SET);
  858. putint32(CDF->fp,CDF->magic_number);
  859. putint32(CDF->fp,CDF->magic_number);
  860.  
  861. /* Write out CDR */
  862.  
  863. Seek (CDF->fp, CDF->CDRoffset, SEEK_SET);
  864. putint32(CDF->fp,CDF->CDR.RecordSize);
  865. putint32(CDF->fp,CDF->CDR.RecordType);
  866. putint32(CDF->fp,CDF->CDR.GDRoffset);
  867.  
  868. CDF->CDR.Version = CDF_LIBRARY_VERSION;
  869. putint32(CDF->fp,CDF->CDR.Version);
  870.  
  871. CDF->CDR.Release = CDF_LIBRARY_RELEASE;
  872. putint32(CDF->fp,CDF->CDR.Release);
  873.  
  874. putint32(CDF->fp,CDF->CDR.Encoding);
  875. putint32(CDF->fp,CDF->CDR.Flags);
  876. putint32(CDF->fp,CDF->CDR.rfuA);
  877. putint32(CDF->fp,CDF->CDR.rfuB);
  878.  
  879. CDF->CDR.Increment = CDF_LIBRARY_INCREMENT;
  880. putint32(CDF->fp,CDF->CDR.Increment);
  881.  
  882. putint32(CDF->fp,CDF->CDR.rfuD);
  883. putint32(CDF->fp,CDF->CDR.rfuE);
  884.  
  885. putbytes(CDF_COPYRIGHT_LEN, CDF->CDR.copyright, CDF->fp);
  886.  
  887. /* Write out GDR */
  888.  
  889. Seek (CDF->fp, CDF->GDRoffset, SEEK_SET);
  890. putint32(CDF->fp,CDF->GDR.RecordSize);
  891. putint32(CDF->fp,CDF->GDR.RecordType);
  892. putint32(CDF->fp,CDF->GDR.VDRhead);
  893. putint32(CDF->fp,CDF->GDR.garbage1);
  894. putint32(CDF->fp,CDF->GDR.ADRhead);
  895. putint32(CDF->fp,CDF->GDR.eof);
  896. putint32(CDF->fp,CDF->GDR.NumVar);
  897. putint32(CDF->fp,CDF->GDR.NumAttr);
  898. putint32(CDF->fp,CDF->GDR.MaxRec);
  899. putint32(CDF->fp,CDF->GDR.NumDims);
  900. putint32(CDF->fp,CDF->GDR.rfuA);
  901. putint32(CDF->fp,CDF->GDR.rfuB);
  902. putint32(CDF->fp,CDF->GDR.rfuC);
  903. putint32(CDF->fp,CDF->GDR.rfuD);
  904. putint32(CDF->fp,CDF->GDR.rfuE);
  905.  
  906. for (dimN = 0; dimN < CDF->GDR.NumDims; dimN++)
  907.    putint32(CDF->fp,CDF->GDR.DimSizes[dimN]);
  908.  
  909. /* Write out VDRs */
  910.  
  911. Var = CDF->varHead;
  912.  
  913. while (Var != NULL) {
  914.   Seek (CDF->fp, Var->VDRoffset, SEEK_SET);
  915.  
  916.   putint32(CDF->fp,Var->VDR.RecordSize);
  917.   putint32(CDF->fp,Var->VDR.RecordType);
  918.   putint32(CDF->fp,Var->VDR.VDRnext);
  919.   putint32(CDF->fp,Var->VDR.DataType);
  920.   putint32(CDF->fp,Var->VDR.MaxRec);
  921.   putint32(CDF->fp,Var->VDR.VXRhead);
  922.   putint32(CDF->fp,Var->VDR.VXRtail);
  923.   putint32(CDF->fp,Var->VDR.Flags);
  924.   putint32(CDF->fp,Var->VDR.rfuA);
  925.   putint32(CDF->fp,Var->VDR.rfuB);
  926.   putint32(CDF->fp,Var->VDR.rfuC);
  927.   putint32(CDF->fp,Var->VDR.REFvarNum);
  928.  
  929.   putbytes(CDF_VAR_FILE_NAME_LEN, Var->VDR.REFfilename, CDF->fp);
  930.  
  931.   putint32(CDF->fp,Var->VDR.NumElem);
  932.   putint32(CDF->fp,Var->VDR.Num);
  933.   putint32(CDF->fp,Var->VDR.rfuD);
  934.   putint32(CDF->fp,Var->VDR.NextendRecs);
  935.  
  936.   putbytes(CDF_VAR_NAME_LEN, Var->VDR.Name, CDF->fp);
  937.  
  938.   for (dimN = 0; dimN < CDF->GDR.NumDims; dimN++)
  939.      putint32(CDF->fp,Var->VDR.DimVarys[dimN]);
  940.  
  941.   if (bitset(Var->VDR.Flags,VAR_FILLVALUE_BIT)) {
  942. #if defined(sun) | defined(MIPSEB) | defined(IBMRS) | defined(HP)
  943.     /* Do nothing. */
  944. #endif
  945. #if defined(vax) | defined(MIPSEL) | defined(__IBMPC__)
  946.     if (CDF->CDR.Encoding == NETWORK_ENCODING)
  947.       xdr_encode (Var->VDR.DataType, Var->VDR.NumElem,
  948.           Var->VDR.FillValue, Var->VDR.FillValue);
  949. #endif
  950.     putbytes (Var->VDR.NumElem * _CDFelemSizes[Var->VDR.DataType],
  951.           Var->VDR.FillValue, CDF->fp);
  952.   }
  953.  
  954.   /* write out VXRs */
  955.  
  956.   Vix = Var->vixHead;
  957.  
  958.   while (Vix != NULL) {
  959.     Seek (CDF->fp, Vix->VXRoffset, SEEK_SET);
  960.  
  961.     putint32(CDF->fp,Vix->VXR.RecordSize);
  962.     putint32(CDF->fp,Vix->VXR.RecordType);
  963.     putint32(CDF->fp,Vix->VXR.VXRnext);
  964.     putint32(CDF->fp,Vix->VXR.Nentries);
  965.     putint32(CDF->fp,Vix->VXR.NusedEntries);
  966.  
  967.     for (i = 0; i < Vix->VXR.Nentries; i++)
  968.        putint32(CDF->fp,Vix->VXR.FirstRec[i]);
  969.     for (i = 0; i < Vix->VXR.Nentries; i++)
  970.        putint32(CDF->fp,Vix->VXR.LastRec[i]);
  971.     for (i = 0; i < Vix->VXR.Nentries; i++)
  972.        putint32(CDF->fp,Vix->VXR.VVRoffset[i]);
  973.  
  974.     Vix = Vix->vixNext;
  975.   }
  976.  
  977.   Var = Var->varNext;
  978. }
  979.  
  980. /* Write out ADRs and AEDRs */
  981.  
  982. Attr = CDF->attrHead;
  983. while (Attr != NULL) {
  984.     Seek (CDF->fp, Attr->ADRoffset, SEEK_SET);
  985.     putint32(CDF->fp,Attr->ADR.RecordSize);
  986.     putint32(CDF->fp,Attr->ADR.RecordType);
  987.     putint32(CDF->fp,Attr->ADR.ADRnext);
  988.     putint32(CDF->fp,Attr->ADR.AEDRhead);
  989.     putint32(CDF->fp,Attr->ADR.Scope);
  990.     putint32(CDF->fp,Attr->ADR.Num);
  991.     putint32(CDF->fp,Attr->ADR.NumEntries);
  992.     putint32(CDF->fp,Attr->ADR.MaxEntry);
  993.     putint32(CDF->fp,Attr->ADR.rfuA);
  994.     putint32(CDF->fp,Attr->ADR.rfuB);
  995.     putint32(CDF->fp,Attr->ADR.rfuC);
  996.     putint32(CDF->fp,Attr->ADR.rfuD);
  997.     putint32(CDF->fp,Attr->ADR.rfuE);
  998.  
  999.     putbytes(CDF_ATTR_NAME_LEN, Attr->ADR.Name, CDF->fp);
  1000.  
  1001.     Entry = Attr->entryHead;
  1002.     while (Entry != NULL) {
  1003.     Seek (CDF->fp, Entry->AEDRoffset, SEEK_SET);
  1004.     putint32(CDF->fp,Entry->AEDR.RecordSize);
  1005.     putint32(CDF->fp,Entry->AEDR.RecordType);
  1006.     putint32(CDF->fp,Entry->AEDR.AEDRnext);
  1007.     putint32(CDF->fp,Entry->AEDR.AttrNum);
  1008.     putint32(CDF->fp,Entry->AEDR.DataType);
  1009.     putint32(CDF->fp,Entry->AEDR.Num);
  1010.     putint32(CDF->fp,Entry->AEDR.NumElem);
  1011.     putint32(CDF->fp,Entry->AEDR.rfuA);
  1012.     putint32(CDF->fp,Entry->AEDR.rfuB);
  1013.     putint32(CDF->fp,Entry->AEDR.rfuC);
  1014.     putint32(CDF->fp,Entry->AEDR.rfuD);
  1015.     putint32(CDF->fp,Entry->AEDR.rfuE);
  1016.  
  1017.     Nbytes = _CDFelemSizes[Entry->AEDR.DataType] * Entry->AEDR.NumElem;
  1018.  
  1019. #if defined(sun) | defined(MIPSEB) | defined(IBMRS) | defined(HP)
  1020.         /* Do nothing. */
  1021. #endif
  1022.  
  1023. #if defined(vax) | defined(MIPSEL) | defined(__IBMPC__)
  1024.     if (CDF->CDR.Encoding == NETWORK_ENCODING)
  1025.        xdr_encode (Entry->AEDR.DataType, Entry->AEDR.NumElem,
  1026.                Entry->AEDR.Value, Entry->AEDR.Value);
  1027. #endif
  1028.  
  1029.     putbytes (Nbytes, Entry->AEDR.Value, CDF->fp);
  1030.  
  1031.     Entry = Entry->entryNext;
  1032.     }
  1033.  
  1034.     Attr = Attr->attrNext;
  1035. }
  1036.  
  1037. return Pstatus;
  1038. }
  1039.